package com.ant.business.ocr.controller;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.teautil.Common;
import com.ant.business.ocr.entity.Explorer;
import com.ant.business.ocr.service.ExplorerService;
import com.ant.business.oss.AliyunOSS;
import com.ant.common.annotation.AuthIgnore;
import com.ant.common.result.ResponseResult;
import com.ant.common.utils.DateUtils;
import com.ant.common.utils.FastMap;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sprite.utils.UtilString;
import com.sprite.utils.mimetype.UtilMimeType;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @description: 智能结构化识别
 * @author: yy
 * @date: 2023/8/16 10:03
 */
@RestController
@RequestMapping(value = "/ocr")
@Slf4j
@Api(tags = "智能结构化识别管理")
public class AiExplorerController {

    private static final String secretId = "AKIDb6TLKScqulaRAjCYqAd8SaccYHl25wdK";
    private static final String SecretKey = "2tY1HQPMTRH6j9Qj5RejfRya7TqEOJ1g";

    private static final String PRE_STR = ", 请给我列出(药品编码)，(药品名称)，" +
            "(计量单位)包含盒、瓶、片等，(药品厂家)，(销售门店)，(销售员或营业员)，(单据日期)格式为yyyy-MM-dd HH:mm:ss，(单据号或单号)，" +
            "(药品数量)是数字没有值显示为0，(销售金额)没有值显示为0，其他没有值的显示为空，" +
            "一定要识别准确，每一个药品生成一条记录，不要汇总，以json格式返回";

    @Autowired
    private ExplorerService explorerService;

    @Autowired
    private AliyunOSS aliyunOSS;

    /*@PostMapping(value = "/explorer", name = "智能结构化识别小票数据")
    @ApiOperation("智能结构化识别小票数据")
    @AuthIgnore
    public ResponseResult explorer(@RequestBody ExplorerVo explorerVo) {
        try {
            if (StringUtils.isBlank(explorerVo.getImageUrl())) {
                return ResponseResult.fail("缺失图片路径参数");
            }
            LambdaQueryWrapper<Explorer> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Explorer::getImageUrl, explorerVo.getImageUrl());
            Explorer data = explorerService.getOne(queryWrapper);
            if (data != null && StringUtils.isNotBlank(data.getExplorer())) {
                String explorer = data.getExplorer();
                FastMap fastMap = FastMap.fromObject(explorer);
                List<FastMap> structuralItems = fastMap.getList("StructuralItems");
                List<FastMap> newList = new ArrayList<>();
                for (FastMap structuralItem : structuralItems) {
                    String name = structuralItem.getString("Name");
                    String value = structuralItem.getString("Value");
                    FastMap map = new FastMap();
                    map.put("name", name);
                    map.put("value", value);
                    newList.add(map);
                }

                log.info("newList: {} {}", newList, PRE_STR);
                return ResponseResult.success(newList.toString() + PRE_STR);
            }
            log.info("[ImageUrl]{}:", explorerVo.getImageUrl());
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(secretId, SecretKey);
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            SmartStructuralOCRRequest req = new SmartStructuralOCRRequest();
            req.setImageUrl(explorerVo.getImageUrl());
            // 返回的resp是一个SmartStructuralOCRResponse的实例，与请求对象对应
            SmartStructuralOCRResponse resp = client.SmartStructuralOCR(req);
            // 输出json格式的字符串回包
            String explorer = SmartStructuralOCRResponse.toJsonString(resp);

            FastMap fastMap = FastMap.fromObject(explorer);
            List<FastMap> structuralItems = fastMap.getList("StructuralItems");
            List<FastMap> newList = new ArrayList<>();
            for (FastMap structuralItem : structuralItems) {
                String name = structuralItem.getString("Name");
                String value = structuralItem.getString("Value");
                FastMap map = new FastMap();
                map.put("name", name);
                map.put("value", value);
                newList.add(map);
            }
            log.info("newList: {} {}", newList, PRE_STR);

            Explorer build = Explorer.builder().explorer(explorer).build();
            build.setCreateTime(System.currentTimeMillis());
            build.setImageUrl(explorerVo.getImageUrl());
            explorerService.save(build);
            return ResponseResult.success(explorer);
        } catch (Exception e) {
            return ResponseResult.fail("智能结构化识别失败：" + e.getMessage());
        }
    }*/


    @RequestMapping(value = "/image")
    @AuthIgnore
    public ResponseResult imageUpload(MultipartFile[] files, HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("[AiExplorerController] start");
      /*  MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        Collection<MultipartFile> fileList = fileMap.values();*/
        String targetPath = saveImage(files);

        //OCR
        if (StringUtils.isBlank(targetPath)) {
            return ResponseResult.fail("上传图片失败");
        }
        LambdaQueryWrapper<Explorer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Explorer::getImageUrl, targetPath);
        Explorer data = explorerService.getOne(queryWrapper);
        if (data != null && StringUtils.isNotBlank(data.getExplorer())) {
            String explorer = data.getExplorer();
            FastMap fastMap = FastMap.fromObject(explorer);
            List<FastMap> structuralItems = fastMap.getList("StructuralItems");
            List<FastMap> newList = new ArrayList<>();
            for (FastMap structuralItem : structuralItems) {
                String name = structuralItem.getString("Name");
                String value = structuralItem.getString("Value");
                FastMap map = new FastMap();
                map.put("name", name);
                map.put("value", value);
                newList.add(map);
            }
            // log.info("newList: {}, 请给我列出药品名称（medicineName），药品数量(quantity)，药品厂家(supplier)，以json格式返回", newList);
            return ResponseResult.success(newList.toString() + PRE_STR);
        }
        /**
         * 腾讯云
         */
//        // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
//        // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
//        // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
//        Credential cred = new Credential(secretId, SecretKey);
//        // 实例化一个http选项，可选的，没有特殊需求可以跳过
//        HttpProfile httpProfile = new HttpProfile();
//        httpProfile.setEndpoint("ocr.tencentcloudapi.com");
//        // 实例化一个client选项，可选的，没有特殊需求可以跳过
//        ClientProfile clientProfile = new ClientProfile();
//        clientProfile.setHttpProfile(httpProfile);
//        // 实例化要请求产品的client对象,clientProfile是可选的
//        OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile);
//        // 实例化一个请求对象,每个接口都会对应一个request对象
//        SmartStructuralOCRRequest req = new SmartStructuralOCRRequest();
//        req.setImageUrl(targetPath);
//        // 返回的resp是一个SmartStructuralOCRResponse的实例，与请求对象对应
//        SmartStructuralOCRResponse resp = client.SmartStructuralOCR(req);
//        // 输出json格式的字符串回包
//        String explorer = SmartStructuralOCRResponse.toJsonString(resp);
//            FastMap fastMap = FastMap.fromObject(explorer);
//            List<FastMap> structuralItems = fastMap.getList("StructuralItems");
//            List<FastMap> newList = new ArrayList<>();
//            for (FastMap structuralItem : structuralItems) {
//                String name = structuralItem.getString("Name");
//                String value = structuralItem.getString("Value");
//                FastMap map = new FastMap();
//                map.put("name", name);
//                map.put("value", value);
//                newList.add(map);
//            }
//            Explorer build = Explorer.builder().explorer(explorer).build();
//            build.setCreateTime(System.currentTimeMillis());
//            build.setImageUrl(targetPath);
//            explorerService.save(build);


        /**
         * 阿里云
         */
        String ocrResult = aLiYunOcr(targetPath);
        log.info("ocrResult:  {}", ocrResult + "," + PRE_STR);
        // return ResponseResult.success(newList.toString()+", 请给我列出药品编码(medicineId)，药品名称（medicineName），药品数量(quantity)是数字，药品厂家(supplier)，销售金额(amount)，没有值的显示为空，以json格式返回");
        return ResponseResult.success(ocrResult + PRE_STR);
    }

    private String saveImage(MultipartFile[] fileList) {
        for (MultipartFile file : fileList) {
            if (!file.isEmpty() && file.getSize() != 0) {
                //获取文件格式 例如:.jpg
                String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
                try {
                    String targetPath = uploadFileOSS(file.getInputStream(), null, ext);
                   /* JSONObject data = new JSONObject();
                    data.put("head_url", targetPath);*/
                    return targetPath;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public String uploadFileOSS(InputStream inputStream, String fileName, String suffix) {

        StringBuilder pathBuilder = new StringBuilder();
        if (StringUtils.isBlank(fileName)) {
            fileName = UUID.randomUUID().toString();
        }

        String path = UtilString.place("health/eyeshade/{}/{}/{}/{}",
                DateUtils.getYear(),
                DateUtils.getMonth(),
                DateUtils.getDate(), fileName);

        pathBuilder.append(path);
        String mimeType = null;
        if (StringUtils.isNoneBlank(suffix)) {
            mimeType = UtilMimeType.mimeTypeByFileSuffix(suffix);
            pathBuilder.append(".").append(suffix);
        }
        String targetPath = pathBuilder.toString();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setObjectAcl(CannedAccessControlList.PublicRead);
        if (mimeType != null) {
            objectMetadata.setContentType(mimeType);
        }
        try {
            aliyunOSS.upload("hipeeimg", targetPath, inputStream, objectMetadata);

            return "https://img.hipee.cn/" + targetPath;
        } catch (Exception e) {
            log.info("[UploadService][uploadOSS][upload oss is error]", e);
            return "";
        }
    }


    /**
     * 使用AK&SK初始化账号Client
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @return Client
     * @throws Exception
     */
    public static com.aliyun.ocr_api20210707.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，您的 AccessKey ID
                .setAccessKeyId("LTAI5tDPbJiDxhVHEnZory5f")
                // 必填，您的 AccessKey Secret
                .setAccessKeySecret("w2dnaaXHB7MevAqywBc61svok8nw6V");
        // Endpoint 请参考 https://api.aliyun.com/product/ocr-api
        config.endpoint = "ocr-api.cn-hangzhou.aliyuncs.com";
        return new com.aliyun.ocr_api20210707.Client(config);
    }


    public String aLiYunOcr(String url) throws Exception {
        // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        // 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html
        com.aliyun.ocr_api20210707.Client client = this.createClient(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        com.aliyun.ocr_api20210707.models.RecognizeAdvancedRequest recognizeAdvancedRequest = new com.aliyun.ocr_api20210707.models.RecognizeAdvancedRequest()
                .setUrl(url);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        com.aliyun.ocr_api20210707.models.RecognizeAdvancedResponse resp = client.recognizeAdvancedWithOptions(recognizeAdvancedRequest, runtime);
        String message = resp.getBody().getMessage();
        System.out.println(message);
        String result = Common.toJSONString(resp);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            JSONObject body = jsonObject.getJSONObject("body");
            JSONObject data = body.getJSONObject("data");
            String content = data.getString("content");
            return content;
        }
        return "";
        //com.aliyun.teaconsole.Client.log(com.aliyun.teautil.Common.toJSONString(resp));
    }


}
